package com.leon.learnenginespace.drools.bl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.leon.common.entity.RequestBodyVo;
import com.leon.common.entity.ResponseVo;
import com.leon.learnenginespace.drools.dao.GeneralRulesMapper;
import com.leon.learnenginespace.drools.pojo.TDrlNRuleBindColumnConfig;
import com.leon.learnenginespace.drools.support.DroolsCenterFrameworkHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.kie.api.runtime.KieSession;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description: 规则处理
 * @author: WT
 * @date: 2024/3/31 18:29
 * @Version 1.0
 **/
@Component
@Slf4j
public class GeneralRulesBL {

    @Resource
    private DroolsCenterFrameworkHelper droolsCenterFrameworkHelper;
    @Resource
    private GeneralRulesMapper generalRulesMapper;

    public static Map<String, Map<String, Object>> RULE_PARAM_MAP = new HashMap<>();

    /**
     * 执行业务规则
     *
     * @param requestBody
     * @return ResponseVo
     */

    public ResponseVo<?> dealData(RequestBodyVo<?> requestBody) {
        ResponseVo<?> responseVo = new ResponseVo<>();
        log.info("通用校验接口-start");
        JSONObject reqBodyJsonObject = (JSONObject) requestBody.getBody();
        JSONArray ruleMessageDTOList = new JSONArray();
        ((JSONObject) requestBody.getBody()).put("ruleMessageDTOList", ruleMessageDTOList);
        RequestBodyVo<?>.RequestHead header = requestBody.getHeader();
        JSONObject responseVoBody;
        responseVoBody = new JSONObject();
        responseVo.setBody(responseVoBody);
        if (StringUtils.isEmpty(header.getSceneCode())) {
            return responseVo.error(header, "场景编码为空");
        }
        try {
            //1、参数配置化  获取绑定规则配置的参数
            reqBodyJsonObject.put("ruleColumns", paramConfig(header.getSceneCode(), false));
            //2、报文插入kieSession
            KieSession kieSession = droolsCenterFrameworkHelper.getKieSession(header.getSceneCode());
            if (kieSession == null) {
                responseVo = responseVo.success(header);
                requestBody.getHeader().setRetMsg("场景无规则，默认通过");
                return responseVo;
            }
            kieSession.insert(requestBody.getBody());
            //3、执行规则
            List<String> notRuleLists = getReidRule(header.getSceneCode());
            int fireCount;
            if (notRuleLists != null) {
                //白名单，过滤掉不需要执行的规则
                fireCount = fireNotRule(notRuleLists, kieSession);
            } else {
                //白名单没有数据，正常执行规则
                fireCount = kieSession.fireAllRules();
            }
            kieSession.dispose();
            //4、组装返回报文
            log.info("触发了{}条规则", fireCount);
            responseVoBody.put("errorMessage", "");
            responseVoBody.put("ruleMessageDTOList", ((JSONObject) requestBody.getBody()).get("ruleMessageDTOList"));
            responseVo.setValue(header, responseVoBody, 0L);
        } catch (Exception e) {
            log.error("执行规则异常：", e);
            responseVoBody.put("errorMessage", "RD020接口执行规则异常：" + e);
            responseVo.setBody(responseVoBody);
            responseVo.error(header, "RD020接口执行规则异常");
            return responseVo;
        }
        log.info("通用校验接口-end");
        return responseVo;

    }

    /**
     * 规则参数配置化
     */
    public Map<String, Object> paramConfig(String sceneCode, boolean isUpdate) {
        List<TDrlNRuleBindColumnConfig> columnConfigs;
        Map<String, Object> ruleParam;
        if (isUpdate) {
            columnConfigs = generalRulesMapper.queryRuleColumn(sceneCode);
            ruleParam = new HashMap<>();
            for (TDrlNRuleBindColumnConfig columnConfig : columnConfigs) {
                ruleParam.put(columnConfig.getParamName(), columnConfig.getValue());
            }
            RULE_PARAM_MAP.put(sceneCode, ruleParam);
        } else {
            ruleParam = RULE_PARAM_MAP.get(sceneCode);
        }
        return ruleParam;
    }

    /**
     * 过滤掉白名单中的规则，执行规则
     * 查询redis，存储到notRuleListsFinal中,通过报文获取保单号，用保单号在redis中查询，查询到对应的规则名
     */
    private int fireNotRule(List<String> notRuleLists, KieSession kieSession) {
        final List<String> notRuleListsFinal = notRuleLists;
        return kieSession.fireAllRules(match -> {
            for (String s : notRuleListsFinal) {
                if (match.getRule().getName().equals(s)) {
                    return false;
                }
            }
            return true;
        });
    }

    /**
     * 获取白名单
     */
    private List<String> getReidRule(String sceneCode) {
        List<String> notRuleLists = new ArrayList<>();
        if (CollectionUtils.isEmpty(notRuleLists)) {
            return null;
        }
        return notRuleLists;
    }
}